package com.pug.zixun.config.interceptor.login;

import com.pug.zixun.commons.anno.IgnoreToken;
import com.pug.zixun.commons.enums.AdminUserResultEnum;
import com.pug.zixun.commons.ex.PugValidatorException;
import com.pug.zixun.commons.utils.fn.asserts.Vsserts;
import com.pug.zixun.config.redis.AdminRedisKeyManager;
import com.pug.zixun.config.redis.IJwtBlackService;
import com.pug.zixun.local.UserThreadLocal;
import com.pug.zixun.service.jwt.JwtService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 挤下线使用
 *
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 飞哥B站地址：https://space.bilibili.com/490711252
 * 记得关注和三连哦！
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2022/5/16$ 22:27$
 */
@Component
@Slf4j
public class PassportLogoutInterceptor implements HandlerInterceptor, AdminRedisKeyManager {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    @Qualifier("jwtBlackStringService")
    private IJwtBlackService jwtBlackService;

    @Autowired
    private JwtService jwtService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // handler从object对象转换成具体的目标对象HandlerMethod
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 获取执行的方法
        Method method = handlerMethod.getMethod();
        if (method.getAnnotation(IgnoreToken.class) != null ||
                handlerMethod.getBeanType().getAnnotation(IgnoreToken.class) != null) {
            return true;
        }

        // 获取用户请求的token
        String token = jwtService.getToken(request);
        // 判断当前token是不是一个退出token，如果存在黑名单直接返回过期或者无效
        if(jwtBlackService.isBlackList(token)){
            throw new PugValidatorException(AdminUserResultEnum.TOKEN_ERROR_STATUS);
        }

        /*********************这里是用户输入的信息********************/
        // 获取用户传递过来的tokenuuid
        String tokenUuid = request.getHeader(TOKEN_UUID_NAME);
        // 如果没有获取到，说明没有登录
        Vsserts.isEmptyEx(tokenUuid, AdminUserResultEnum.USER_LOGIN_UUID_EMPTY);

        // *******************从redis获取uuid********************/
        String tokenUserId = request.getHeader(TOKEN_USERID_NAME);
        String tokenUuidKey = USER_LOGIN_LOGOUT_KEY + tokenUserId;
        String cacheUuid = stringRedisTemplate.opsForValue().get(tokenUuidKey);
        // 如果没有获取到，说明没有登录
        Vsserts.isEmptyEx(tokenUuid, AdminUserResultEnum.USER_LOGIN_UUID_EMPTY);
        // *******************比较********************/
        // 如果你当前访问的uuid和缓存的uuid不同，就说明你在别的地方登录了。
        if (!tokenUuid.equalsIgnoreCase(cacheUuid)) {
            throw new PugValidatorException(AdminUserResultEnum.USER_LOGIN_SAME);
        }

        return true;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        UserThreadLocal.remove();
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserThreadLocal.remove();
    }
}
